from diff_match_patch import diff_match_patch

from django.db import models
from django.contrib.auth.models import User

def diff(txt1, txt2):
    """Create a 'diff' from txt1 to txt2."""
    dmp = diff_match_patch()
    patch = dmp.patch_make(txt1, txt2)
    return dmp.patch_toText(patch)

def pretty_html(txt1, txt2):
    dmp = diff_match_patch()
    diffs = dmp.diff_main(txt1, txt2)
    return dmp.diff_prettyHtml(diffs)

class WikiArticle(models.Model):
    author = models.ForeignKey(User)
    #title = models.CharField(max_length=255, unique=True)
    content = models.TextField(blank=True)
    initial_content = models.TextField(blank=True)

    #pub_date = models.DateTimeField('date published', auto_now=1)
    #is_mutable = models.BooleanField(default=True, blank=True)

    #parent = models.ForeignKey('self', blank=True, null=True, related_name='discussion')

    class Meta:
        abstract = True

    def save(self):
        if self.id is None: # creating new article
            new_article = True
            self.initial_content = self.content
        else:
            new_article = False

        super(WikiArticle, self).save()
        self.create_revision(new_article)

    def create_revision(self, new_article):
        if new_article is True:
            content_diff = diff(self.content, self.content) # don't know if this is always empty string
            revision = 1
        else:
            latest_revision = self.revision_set.latest()
            revision = latest_revision.revision+1
            reverted_content = self.get_reverted(latest_revision)
            content_diff = diff(reverted_content, self.content)

        return self.revision_set.create(
            comment="",
            editor=self.author,
            content_diff=content_diff,
            revision = revision)

    def get_reverted(self, revision):

        dmp = diff_match_patch()
        # well, it *will* be the old content
        result = self.initial_content

        revisions = self.revision_set.filter(revision__lte=revision.revision).order_by('revision')

        for revision in revisions:
            patches = dmp.patch_fromText(revision.content_diff)
            result = dmp.patch_apply(patches, result)[0]

        return result

    def get_pretty_html(self, txt1, txt2):
        return pretty_html(txt1, txt2)

    def get_reverted_from_int(self, revision):
        revisions = self.revision_set.filter(revision=revision)
        if len(revisions) == 0:
            return False

        return self.get_reverted(revisions[0])

class WikiRevision(models.Model):
    #article = models.ForeignKey(WikiArticle)
    editor = models.ForeignKey(User)

    revision = models.IntegerField("Revision Number")
    content_diff = models.TextField()
    comment = models.CharField(blank=True, max_length=250)
    date_commited = models.DateTimeField('date commited', auto_now_add=1)

    class Meta:
        abstract = True
        get_latest_by  = 'date_commited'
        unique_together = (("article", "revision"),)

#    def __unicode__(self):
#        return "r%d for %s" % ( self.revision, self.article.title )

    def save(self):
    #    try:
    #        self.revision = self.article.revision_set.latest().revision + 1
    #    except BaseException:
    #        self.revision = 1
        super(WikiRevision, self).save()

